#pragma once
#include <windows.h>
#include <d2d1.h>
#include <math.h>
#include <vector>

#include "Display.h"
#include "Tool.h"
#include "Message.h"
#include "WinComponent.h"

namespace core{
    namespace form
    {
        namespace form_msg = util::message;
        typedef display::AbstractPlayer IPlayer;
        typedef display::AnimationManager AniManager;

        enum WndClass{
            main_form,
            _COUNT
        };

        typedef struct Mainform_control_struct{
            POINTS dragging_start_pos_buf;
            time_t last_time_left_click;
        }MAIN_CONTROL_STRUCT;
 
        typedef struct Mainform_component_struct{
            component::MenuTree * pRight_click_menu;

            component::MenuInstance GetRootMenu();
            ~Mainform_component_struct();
        }MAIN_COMPONENTS;

        static WNDCLASSEX classRegistered[WndClass::_COUNT];

        static LPCTSTR classNameGroup[WndClass::_COUNT];

        static bool hasWndClassRegistered = false;

        
        class AbstractForm{
        public:
            AbstractForm(LPCTSTR windowName, HWND hWnd, int w, int h);

            void SetMessageHandlerToApp(form_msg::IMessageHandler * pApp);

            virtual ~AbstractForm();

            HRESULT ShowForm();

            BOOL UpdateForm();

            WINBOOL GetWndRect(LPRECT lprect);

            WINBOOL Move(int x, int y);

            bool MsgSendToApp(form_msg::MessageType msg, void * param);

            protected:
            HWND hWnd;
            private:
            LPCTSTR name;
            form_msg::IMessageHandler * pIapp;
        };

        class AbstractD2DForm : public AbstractForm{
        public:

            AbstractD2DForm(LPCTSTR windowName, HWND hWnd, int w, int h);

            HRESULT CreateDeviceIndependentResources();

            virtual HRESULT CreateDeviceResources(); 

            virtual ~AbstractD2DForm();
        protected:
            // std::mutex player_lock;
            ID2D1Factory* pDirect2dFactory;
            ID2D1HwndRenderTarget* pRenderTarget;
        };

        class MainForm : public AbstractD2DForm{
        public:
            MainForm(LPCTSTR windowName, HWND hwnd, int w, int h);

            virtual ~MainForm();

            virtual HRESULT CreateDeviceResources();

            void OpenPopMenu(int mouse_x, int mouse_y);

            static LRESULT CALLBACK origin_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);

            static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);

        protected:
            HRESULT PaintDefault();
        private:
            MAIN_CONTROL_STRUCT * pControl;
            MAIN_COMPONENTS * pComponents;
            IPlayer* pMain_audio_player;
            
            IPlayer * test_player;

            
            AniManager ani_manager;
        };

        class FormFactory{
        public:
            FormFactory(LPVOID app, WndClass wndClass, HINSTANCE hInstance);

            static void registerWndClass(HINSTANCE hInstance);

            static void UnregisterWndClass();

            void SetWndSize(int w, int h);

            void SetStyle(DWORD style);

            HRESULT CreateForm(AbstractForm ** pform);
        private:
            WndClass wndClass;
            LPCTSTR lpWindowName;
            DWORD dwStyle;
            int X;
            int Y;
            int nWidth;
            int nHeight;
            HWND hWndParent;
            HMENU hMenu;
            HINSTANCE hInstance;
            LPVOID lpApp;
        };
    }
}